﻿using System;
using System.IO;

namespace TrekBattle
{
    class Fleet
    {
        private readonly String FleetFilename;
        private string FleetName;
        private int NumberOfShips;
        private Ship[] Ships;
        private Ship[] ShipsDestroyed;

        public Fleet(string filename)
        {
            FleetFilename = filename;
            try
            {
                StreamReader fin = new StreamReader(filename);

                SetupFleet(fin);
                LoadFleet(fin);

                string extraInput = fin.ReadToEnd();

                // If anything else is input, inform the user
                if (extraInput != null && extraInput.Trim() != "")
                    EndProgram("More ships than stated in " + filename);

                fin.Close();
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("Program failed with the following error");
                Console.WriteLine(filename + " file not found");
                Environment.Exit(0);
            }
        }

        private void SetupFleet(StreamReader fin)
        {
            // First input file line
            FleetName = fin.ReadLine(); // Can be blank

            string line = fin.ReadLine();
            if (!Int32.TryParse(line, out NumberOfShips) || NumberOfShips <= 0)
                EndProgram("Invalid number of ships in " + FleetFilename);
            Ships = new Ship[NumberOfShips];
        }

        private void LoadFleet(StreamReader fin)
        {
            // And setup each ship listed in the remainder of the input file
            for (int i = 0; i < (int)NumberOfShips; i++)
                Ships[i] = new Ship(fin, FleetFilename);
        }

        public string GetName()
        {
            return FleetName;
        }

        public void DisplayRoundReport(int round)
        {
            if (ShipsDestroyed != null) // Then a ship was destroyed
            {
                Console.WriteLine("After round " + round.ToString() + " the " + FleetName + " fleet has lost");
                foreach (Ship ship in ShipsDestroyed)
                    Console.WriteLine("  " + ship.GetName() + " destroyed");
                Console.WriteLine(); // Blank line for readability
            }
        }

        public void DisplayDamageReport()
        {
            foreach (Ship ship in Ships)
                Console.WriteLine("    " + ship.GetName() + " - " + ship.DamageLevel());
        }

        public int ShipCount()
        {
            return Ships.Length;
        }

        public int ShipsLostCount()
        {
            return (NumberOfShips - Ships.Length);
        }

        private int CountDestroyedShips()
        {
            int counter = 0;
            foreach (Ship ship in Ships)
            {
                if (ship.isDestroyed() == true)
                    counter += 1;
            }

            return counter;
        }

        public void RemoveDestroyedShips()
        {
            int deadShipCount = CountDestroyedShips();

            if (deadShipCount > 0)
            {
                Ship[] shipsClone = (Ship[])Ships.Clone();
                Ships = new Ship[Ships.Length - deadShipCount];
                int i = 0;

                ShipsDestroyed = new Ship[deadShipCount];
                int j = 0;

                foreach (Ship ship in shipsClone)
                {
                    if (ship.isDestroyed() == false)
                        Ships[i++] = ship;
                    else
                        ShipsDestroyed[j++] = ship;
                }
            }
            else
                ShipsDestroyed = null;
        }

        public Ship[] GetShips()
        {
            return Ships;
        }

        public Ship GetShip(int shipIndex)
        {
            return Ships[shipIndex];
        }

        public int GetStartingFleetSize()
        {
            return NumberOfShips;
        }

        public bool HasShipsAlive()
        {
            return Ships.Length > 0;
        }

        private static void EndProgram(string errorText)
        {
            Console.WriteLine("Program failed with the following error");
            Console.WriteLine(errorText);
            Environment.Exit(0);
        }
    }
}